﻿using Zgq.CommonTools;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Text;

namespace Zgq.CommonTools
{
    public static class ExtendClass
    {
        public static void CusAppend(this StringBuilder sqlStrSb, string str)
        {
            sqlStrSb.Append(str);
        }
        static Type[] valTypes = new Type[] { typeof(string), typeof(DateTime), typeof(bool) };

        public static void ValConvertObj(ref object oVal)
        {
            //object result = null;
            if (oVal != null)
            {
                var oValType = oVal.GetType();
                if (valTypes.Contains(oValType))
                    oVal = $"'{oVal}'";
                //else
                //    result = oVal.ToString();
            }
            //return result;
        }
        public static object DynamicInvoke(this Expression expression)
        {
            var oVal = Expression.Lambda(expression).Compile().DynamicInvoke();

            ValConvertObj(ref oVal);

            return oVal;
        }

        public static T GetCellVal<T>(this DataRow dr, string colName)
        {
            T t = default(T);
            if (!string.IsNullOrEmpty(colName) && dr.Table.Columns.Contains(colName))
            {
                object objVal = dr[colName];
                Type _tBaseType = ReflectionHelper.GetUnderlyingType(typeof(T));
                if (objVal != DBNull.Value)
                    t = (T)Convert.ChangeType(objVal, _tBaseType, System.Globalization.CultureInfo.InvariantCulture);
            };
            return t;
        }

        /// <summary>
        /// 拷贝对象下面所有的属性
        /// </summary>
        /// <param name="sourceObj">原对象</param>
        /// <param name="destObj">目标对象</param>
        public static void ObjectPropertysCopyFrom(this object destObj, object sourceObj)
        {
            Type sType = sourceObj.GetType();
            Type dType = destObj.GetType();
            // if (type != tempType) throw new Exception("对象类型不一致");

            PropertyInfo[] properties = dType.GetProperties(); //BindingFlags.Instance | BindingFlags.Public | System.Reflection.BindingFlags.DeclaredOnly);

            foreach (PropertyInfo info in properties)
            {
                PropertyInfo pi = sType.GetProperty(info.Name, info.PropertyType);

                if (pi != null && pi.PropertyType == info.PropertyType)
                {
                    object o = pi.GetValue(sourceObj, null);
                    if (info.SetMethod != null)
                        info.SetValue(destObj, o, null);
                }
            }
        }

        /// <summary> 
        /// DataTable转为json 
        /// </summary> 
        /// <param name="obj">对象</param> 
        /// <param name="isFirstType">第一行</param> 
        /// <returns>json数据</returns> 
        public static List<Dictionary<string, object>> ToDictionAryList(this object obj, bool isFirstType = false)
        {
            List<Dictionary<string, object>> dicList = new List<Dictionary<string, object>>();

            DataTable dt = obj as DataTable;

            if (dt == null)
                return dicList;

            Dictionary<string, object> dic = null;
            if (isFirstType)
            {
                dic = new Dictionary<string, object>();

                foreach (DataColumn dc in dt.Columns)
                {
                    dic.Add(dc.ColumnName, dc.DataType.ToStringExt());
                }
                dicList.Add(dic);
            }

            foreach (DataRow dr in dt.Rows)
            {
                dic = new Dictionary<string, object>();

                foreach (DataColumn dc in dt.Columns)
                {
                    dic.Add(dc.ColumnName, dr[dc]);
                }
                dicList.Add(dic);
            }

            return dicList;
        }

        public static List<Dictionary<string, List<Dictionary<string, object>>>> DataSetListToDictionAryList(this List<DataSet> dsList, bool isFirstType = false)
        {
            var dicList = new List<Dictionary<string, List<Dictionary<string, object>>>>();

            foreach (DataSet ds in dsList)
            {
                dicList.Add(ds.DataSetToDictionAryList());
            }

            return dicList;
        }

        public static Dictionary<string, List<Dictionary<string, object>>> DataSetToDictionAryList(this DataSet ds, bool isFirstType = false)
        {
            var dsDics = new Dictionary<string, List<Dictionary<string, object>>>();
            for (int i = 0; i < ds.Tables.Count; i++)
            {
                DataTable dt = ds.Tables[i];
                var dtName = dt.TableName;
                if (string.IsNullOrEmpty(dtName))
                    dtName = string.Format("temp{0}", i);
                dsDics.Add(dt.TableName, dt.ToDictionAryList(isFirstType));
            }

            return dsDics;
        }


        public static DataTable ToDataTable(this List<Dictionary<string, object>> dicList, bool isFirstType = true, string tbName = "temp")
        {
            DataTable dataTable = new DataTable(tbName);  //实例化

            // var dicList = dicListObj as List<Dictionary<string, object>>;
            if (dicList == null) return dataTable;
            try
            {
                if (dicList.Count > 0)
                {
                    #region 添加datatable列，并设置为对应类型
                    var firstLineData = dicList[0];
                    if (firstLineData.Keys.Count<string>() == 0)
                    {
                        return dataTable;
                    }

                    if (dataTable.Columns.Count == 0)
                    {
                        if (isFirstType)
                        {
                            foreach (string current in firstLineData.Keys)
                                dataTable.Columns.Add(current, Type.GetType(firstLineData[current].ToStringExt()));

                            //continue;
                        }
                        else
                        {
                            foreach (string current in firstLineData.Keys)
                            {
                                var oVal = firstLineData[current];
                                if (oVal == null)
                                {
                                    foreach (var dic in dicList)
                                    {
                                        oVal = dic[current];
                                        if (oVal != null) break;
                                    }
                                }
                                if (oVal != null)
                                    dataTable.Columns.Add(current, oVal.GetType());
                                else
                                    dataTable.Columns.Add(current);
                            }
                        }
                    }
                    #endregion

                    bool isFirstRow = true;
                    foreach (var dictionary in dicList)
                    {
                        if (isFirstType && isFirstRow)
                        {
                            isFirstRow = false;
                            continue;
                        }

                        DataRow dataRow = dataTable.NewRow();
                        foreach (string current in dictionary.Keys)
                        {
                            try
                            {
                                var val = dictionary[current];
                                if (val != null)
                                    dataRow[current] = val;

                            }
                            catch { }
                        }

                        dataTable.Rows.Add(dataRow); //循环添加行到DataTable中
                    }
                }
            }
            catch
            {
            }
            return dataTable;
        }


        public static DataSet ToDataSet(this Dictionary<string, List<Dictionary<string, object>>> result)
        {
            DataSet ds = new DataSet();
            foreach (var item in result)
            {
                DataTable dt = item.Value.ToDataTable();
                dt.TableName = item.Key;

                ds.Tables.Add(dt);
            }
            return ds;
        }

        public static DataSet[] ToDataSetArray(this List<Dictionary<string, List<Dictionary<string, object>>>> dicList)
        {
            DataSet[] dsArray = new DataSet[dicList.Count];

            for (int i = 0; i < dicList.Count; i++)
            {
                dsArray[i] = dicList[i].ToDataSet();
            }
            return dsArray;
        }


        public static object GetDefault(this Type targetType)
        {
            return targetType.IsValueType ? Activator.CreateInstance(targetType) : null;
        }

        //------------------------------------------------
        public static List<object[]> ToObjArrayList(this object obj, bool isFirstType = true)
        {
            List<object[]> objArrayList = new List<object[]>();

            DataTable dt = obj as DataTable;

            if (dt == null)
                return objArrayList;

            int columnCount = dt.Columns.Count;
            object[] objArray = null;
            if (isFirstType)
            {
                objArray = new object[columnCount];

                for (int i = 0; i < columnCount; i++)
                {
                    var dc = dt.Columns[i];
                    objArray[i] = string.Format("{0}####{1}", dc.ColumnName, dc.DataType);
                }
                objArrayList.Add(objArray);
            }

            foreach (DataRow dr in dt.Rows)
            {
                //objArray = new object[columnCount];

                //for (int i = 0; i < columnCount; i++)
                //    objArray[i] = dr[i];

                //objArrayList.Add(objArray);

                objArrayList.Add(dr.ItemArray);
            }

            return objArrayList;
        }


        public static DataTable ToDataTableByObjArray(this List<object[]> objArrayList, string tbName = "temp")
        {
            DataTable dataTable = new DataTable(tbName);  //实例化

            // var dicList = dicListObj as List<Dictionary<string, object>>;
            if (objArrayList == null) return dataTable;
            try
            {
                if (objArrayList.Count > 0)
                {
                    #region 添加datatable列，并设置为对应类型
                    var firstLineData = objArrayList[0];
                    int columnCount = firstLineData.Length;
                    if (columnCount == 0)
                    {
                        return dataTable;
                    }


                    foreach (string colInfo in firstLineData)
                    {
                        string[] strs = colInfo.Split(new string[] { "####" }, StringSplitOptions.None);
                        dataTable.Columns.Add(strs[0], Type.GetType(strs[1]));
                    }
                    #endregion

                    foreach (var currentLine in objArrayList.Skip(1))
                    {

                        dataTable.Rows.Add(currentLine);
                        //DataRow dataRow = dataTable.NewRow();

                        //for (int i = 0; i < columnCount; i++)
                        //{
                        //    try
                        //    {
                        //        var val = currentLine[i];
                        //        if (val != null)
                        //            dataRow[i] = val;
                        //    }
                        //    catch { }
                        //}

                        //dataTable.Rows.Add(dataRow); //循环添加行到DataTable中
                    }
                }
            }
            catch
            {
            }
            return dataTable;
        }


        /// <summary>
        /// list集合转DataTable，如【list.ListToDataTable(ref dt, "POReceivingRecInfoId" ,createUserId#userId);】
        /// </summary>
        /// <param name="list">list集合</param>
        /// <param name="fields">需要转换的列（名称不一致时，以#分割，如【createUserId#userId】）</param>
        /// <param name="dt">转换后的DataTable</param>
        public static void ListToDataTable<T>(this List<T> list, ref DataTable dt, params string[] fields) where T : class
        {
            if (dt == null)
                throw new Exception("DataTable不能为NULL");
            if (fields == null || fields.Length == 0)
                throw new Exception("要转换的列不能为空");
            Dictionary<string, string> fieldDic = new Dictionary<string, string>();
            foreach (var field in fields)
            {
                string mField, colName;

                if (field.Contains("#"))
                {
                    string[] fieldRels = field.Split('#');
                    mField = fieldRels[0];
                    colName = fieldRels[1];
                }
                else
                    mField = colName = field;

                if (dt.Columns.Contains(colName))
                    throw new Exception(string.Format("存在相同的列【{0}】", colName));

                dt.Columns.Add(colName);

                fieldDic.Add(colName, mField);
            }

            int mListCount = list.Count;
            int newCount = mListCount - dt.Rows.Count;

            if (newCount > 0)
                for (int i = 0; i < newCount; i++)
                    dt.Rows.Add(dt.NewRow());

            int curri = 0;
            foreach (var mitem in list)
            {
                foreach (var item in fieldDic)
                {
                    Type _type = typeof(T);
                    var pi = _type.GetProperty(item.Value);
                    if (pi == null)
                        throw new Exception(string.Format("属性【{0}】不存在", item.Value));
                    object oVal = pi.GetValue(mitem, null);

                    if (oVal != null)
                        dt.Rows[curri][item.Key] = oVal;
                }
                curri++;
            }
        }
    }
}
